/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.google.fant.depc;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;

/**
 * A dependencies convert mojo
 *
 * @goal depc
 * @description Convert maven2 dependencies to fant dependencies.xml
 * @requiresDependencyResolution test
 */

public class ConverterMojo extends AbstractMojo {
    /**
     * The Maven Project.
     *
     * @parameter expression="${project}"
     * @required
     * @readonly
     */
    protected MavenProject project;

    /**
     * @component
     */
    protected ArtifactFactory artifactFactory;

    /**
     * The set of dependencies required by the project 
     * @parameter default-value="${project.artifacts}"
     * @required
     * @readonly
     */
    Set dependencies;

    /**
     * Build directory
     *
     * @parameter expression="${project.build.outputDirectory}"
     * @required
     */
    private File buildDirectory;

    /**
     * Base directory of the project.
     * @parameter expression="${basedir}"
     */
    private File baseDirectory;


    private Map versions = new HashMap();


    private void writeStart(List sb) throws Exception {
        sb.add("<!--This file is generated by fAnt depc maven plugin @ " + new Date().toString() + " -->");
        sb.add("<project name=\"dependencies\" xmlns:fant=\"antlib:com.google.ant.extensions\">");
    }

    private void writeArtifact(final Artifact artifact, List lines) {
        StringBuffer sb = new StringBuffer();
        sb.append("        <dependency groupid=\"");
        sb.append(artifact.getGroupId());
        sb.append("\" artifactid=\"");
        sb.append(artifact.getArtifactId());
        sb.append("\" version=\"");

        if (versions.containsKey(artifact.getId())) {
            sb.append(artifact.getVersion());
        } else {
            sb.append("${");
            sb.append(artifact.getGroupId());
            sb.append(".version}");
        }
        sb.append("\"/>");
        lines.add(sb.toString());
    }

    private void writeEnd(List sb) {
        sb.add("</project>");
    }

    private void resolveVersion(List versionProps) {
        if (dependencies != null && !dependencies.isEmpty()) {
            for (Iterator it = dependencies.iterator(); it.hasNext();) {
                Artifact artifact = (Artifact)it.next();
                String v = (String) versions.get(artifact.getGroupId());
                if (v == null) {
                    versions.put(artifact.getGroupId(), artifact.getVersion());
                    versionProps.add(artifact);
                    continue;
                }
                if (!v.toLowerCase().equals(artifact.getVersion().toLowerCase())) {
                    versions.put(artifact.getId(), artifact.getVersion());
                }
            }
        }
    }

    private void writeVersionProp(final List versionProps, List lines) {
        for (Iterator it = versionProps.iterator(); it.hasNext();) {
            Artifact artifact = (Artifact) it.next();
            StringBuffer sb = new StringBuffer();
            sb.append("    <property name=\"");
            sb.append(artifact.getGroupId());
            sb.append(".version\" value=\"");
            sb.append(artifact.getVersion());
            sb.append("\"/>");
            
            lines.add(sb.toString());
        }
    }

    private void writeEmptyLine(List lines) {
        lines.add("");
    }

    public void execute() throws MojoExecutionException {
        List versionProps = new ArrayList();
        resolveVersion(versionProps);
        List lines = new ArrayList();

        try {
            writeStart(lines);
            writeVersionProp(versionProps, lines);
            writeEmptyLine(lines);
            if (dependencies != null && !dependencies.isEmpty()) {
                lines.add("    <fant:dependencies id=\"project.dependencies\">");                
                for (Iterator it = dependencies.iterator(); it.hasNext();) {
                    Artifact artifact = (Artifact)it.next();
                    writeArtifact(artifact, lines);
                }
                lines.add("    </fant:dependencies>");
            }
            writeEnd(lines);
            File outputFile = new File(baseDirectory, "dependencies.xml");
            FileUtils.writeLines(outputFile, lines);
        } catch (Exception e) {
            e.printStackTrace();
            getLog().debug(e);
            throw new MojoExecutionException(e.getMessage(), e);
        }
    }
}
